package sketch.specs;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.Comment;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;

import sketch.ast.ASTUtils;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

public class UsedVariableVisitorTest extends TestCase {
	
	public static Test suite() {
		return new TestSuite(UsedVariableVisitorTest.class);
	}
	
	public void testFindingEmptyUsedVars() {
		String filePath = "./testfiles/sketch/specs/RedundantCode.java";
		CompilationUnit unit = ASTUtils.astRoot(filePath);
		List<MethodDeclaration> methods = ASTUtils.getMethodsWithAnnotation(unit, "TestSketch");
		//get the comment list
		List<Comment> cs = unit.getCommentList();
		//unit.getLineNumber(position)
		cs = ASTUtils.blockComments(cs);
		
		//get all blocks
		BlockMappingVisitor visitor = new BlockMappingVisitor(cs);
		visitor.visit(unit);
		Map<Comment, Block> results = visitor.getCommentMappings();
		Collection<Block> allblocks = results.values();
		
		//test each method
		for(MethodDeclaration method : methods) {
			//Block block = method.getBody();
			for(Block b : allblocks) {
				SpecValueDeclarationFinder finder = new SpecValueDeclarationFinder(b);
				List<VariableDeclarationStatement> statements = finder.getAllValueDeclaredStatements();
				List<SimpleName> vars = ASTUtils.extractDefinedVariableName(statements);
				if(ASTUtils.isNested(b, method)) {
					
					UsedVariableVisitor usedVarVisitor = new UsedVariableVisitor(vars);
					usedVarVisitor.visit(b);
					Collection<SimpleName> usedVars = usedVarVisitor.getUsedVariables();
					System.out.println("For block: \n" + b);
					System.out.println("Its used variables: ");
					for(SimpleName usedVar : usedVars) {
						System.out.println("   " + usedVar);
					}
					assertTrue(usedVars.isEmpty());
				}
			}
			
		}
	}
	
	public void testFindingUsedVars() {
		System.out.println();
		System.out.println(" -------------------executing testFindingUsedVars-------------------");
		System.out.println();
		String filePath = "./testfiles/sketch/specs/SampleCode.java";
		CompilationUnit unit = ASTUtils.astRoot(filePath);
		List<MethodDeclaration> methods = ASTUtils.getMethodsWithAnnotation(unit, "TestSketch");
		//get the comment list
		List<Comment> cs = unit.getCommentList();
		//unit.getLineNumber(position)
		cs = ASTUtils.blockComments(cs);
		
		//get all blocks
		BlockMappingVisitor visitor = new BlockMappingVisitor(cs);
		visitor.visit(unit);
		Map<Comment, Block> results = visitor.getCommentMappings();
		Collection<Block> allblocks = results.values();
		
		//test each method
		for(MethodDeclaration method : methods) {
			System.out.println("\n=== processing method: " + method.getName());
			
			for(Block b : allblocks) {
				if(ASTUtils.isNested(b, method)) {
					SpecValueDeclarationFinder finder = new SpecValueDeclarationFinder(b);
					List<VariableDeclarationStatement> statements = finder.getAllValueDeclaredStatements();
					List<SimpleName> vars = ASTUtils.extractDefinedVariableName(statements);
					System.out.println("all defined vars: " + vars);
					//the used var
					UsedVariableVisitor usedVarVisitor = new UsedVariableVisitor(vars);
					usedVarVisitor.visit(b);
					Collection<SimpleName> usedVars = usedVarVisitor.getUsedVariables();
					System.out.println("For block: \n" + b);
					System.out.println("Its used variables: ");
					for(SimpleName usedVar : usedVars) {
						System.out.println("   " + usedVar);
					}
					//assertTrue(usedVars.isEmpty());
				}
			}
		}
	}
}
